﻿#!/bin/bash

# 定义颜色变量，用于日志输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # 无颜色

# 定义常量
CONTAINER_NAME="net8_site"
IMAGE_NAME="vopipi/net8_site"
PROJECT_DIR="/home/docker_site/asp-net8-demo"
PUBLISH_SCRIPT="$PROJECT_DIR/Net8.Project.Publish.Linux.sh"
PUBLISH_DIR="$PROJECT_DIR/.PublishFiles"
HOST_PORT=8082
CONTAINER_PORT=9291

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
    exit 1
}

# 检查命令执行状态
check_status() {
    if [ $? -ne 0 ]; then
        log_error "$1"
    else
        log_info "$2"
    fi
}

# 停止容器
stop_container() {
    log_info "检查容器 $CONTAINER_NAME 是否运行..."
    if docker ps -q --filter "name=$CONTAINER_NAME" | grep -q .; then
        log_info "停止容器 $CONTAINER_NAME..."
        docker stop "$CONTAINER_NAME"
        check_status "停止容器失败" "容器 $CONTAINER_NAME 已停止"
    else
        log_info "容器 $CONTAINER_NAME 未运行，跳过停止步骤"
    fi
}

# 删除容器
remove_container() {
    log_info "检查容器 $CONTAINER_NAME 是否存在..."
    if docker ps -aq --filter "name=$CONTAINER_NAME" | grep -q .; then
        log_info "删除容器 $CONTAINER_NAME..."
        docker rm "$CONTAINER_NAME"
        check_status "删除容器失败" "容器 $CONTAINER_NAME 已删除"
    else
        log_info "容器 $CONTAINER_NAME 不存在，跳过删除步骤"
    fi
}

# 删除镜像
remove_image() {
    log_info "检查镜像 $IMAGE_NAME 是否存在..."
    if docker images -q "$IMAGE_NAME" | grep -q .; then
        log_info "删除镜像 $IMAGE_NAME..."
        docker rmi "$IMAGE_NAME"
        check_status "删除镜像失败" "镜像 $IMAGE_NAME 已删除"
    else
        log_info "镜像 $IMAGE_NAME 不存在，跳过删除步骤"
    fi
}

# 发布项目
publish_project() {
    log_info "检查项目目录 $PROJECT_DIR 是否存在..."
    if [ ! -d "$PROJECT_DIR" ]; then
        log_error "项目目录 $PROJECT_DIR 不存在"
    fi
    
    log_info "切换到项目目录: $PROJECT_DIR"
    cd "$PROJECT_DIR" || log_error "无法切换到项目目录"
    
    log_info "检查发布脚本 $PUBLISH_SCRIPT 是否存在..."
    if [ ! -f "$PUBLISH_SCRIPT" ]; then
        log_error "发布脚本 $PUBLISH_SCRIPT 不存在"
    fi
    
    log_info "检查发布脚本是否可执行..."
    if [ ! -x "$PUBLISH_SCRIPT" ]; then
        log_warn "发布脚本不可执行，尝试添加执行权限..."
        chmod +x "$PUBLISH_SCRIPT"
        check_status "无法添加执行权限" "已添加执行权限"
    fi
    
    log_info "执行发布脚本..."
    "$PUBLISH_SCRIPT"
    check_status "发布脚本执行失败" "项目发布成功"
}

# 构建镜像
build_image() {
    log_info "检查发布目录 $PUBLISH_DIR 是否存在..."
    if [ ! -d "$PUBLISH_DIR" ]; then
        log_error "发布目录 $PUBLISH_DIR 不存在，可能是发布过程失败"
    fi
    
    log_info "切换到发布目录: $PUBLISH_DIR"
    cd "$PUBLISH_DIR" || log_error "无法切换到发布目录"
    
    log_info "检查发布目录中是否存在 Dockerfile..."
    if [ ! -f "Dockerfile" ]; then
        log_error "发布目录中缺少 Dockerfile"
    fi
    
    log_info "构建 Docker 镜像: $IMAGE_NAME..."
    docker build -t "$IMAGE_NAME" .
    check_status "镜像构建失败" "镜像 $IMAGE_NAME 构建成功"
}

# 启动容器
start_container() {
    log_info "检查主机端口 $HOST_PORT 是否被占用..."
    if lsof -Pi :$HOST_PORT -sTCP:LISTEN -t >/dev/null ; then
        log_error "主机端口 $HOST_PORT 已被占用，请释放端口后重试"
    fi
    
    log_info "启动容器 $CONTAINER_NAME..."
    docker run --name "$CONTAINER_NAME" \
               -d \
               --restart=always \
               -v /etc/localtime:/etc/localtime \
               -p "$HOST_PORT:$CONTAINER_PORT" \
               "$IMAGE_NAME"
    check_status "容器启动失败" "容器 $CONTAINER_NAME 启动成功"
    
    log_info "验证容器是否运行..."
    sleep 2  # 等待容器启动
    if ! docker ps -q --filter "name=$CONTAINER_NAME" | grep -q .; then
        log_error "容器 $CONTAINER_NAME 启动后立即退出，请检查容器日志"
    fi
    
    log_info "容器 $CONTAINER_NAME 运行中，端口映射: $HOST_PORT -> $CONTAINER_PORT"
}

# 主函数
main() {
    log_info "===== 开始执行 .NET 8 应用 Docker 部署脚本 ====="
    
    stop_container
    remove_container
    remove_image
    publish_project
    build_image
    start_container
    
    log_info "===== 部署完成 ====="
    log_info "应用已部署到容器: $CONTAINER_NAME"
    log_info "访问地址: http://localhost:$HOST_PORT"
}

# 执行主函数
main